<template>
  <div class="xtx-city" ref="target">
    <div
      class="select"
      @click="handleShowSelectDown"
      :class="{ active: selectDownBox }"
    >
      <span class="placeholder" v-if="!location">请选择配送地址</span>
      <span class="value" v-if="location">{{ location }}</span>
      <i class="iconfont icon-angle-down"></i>
    </div>
    <div class="option" v-if="selectDownBox">
      <template v-if="list.length">
        <span
          class="ellipsis"
          v-for="item in list"
          :key="item.code"
          @click="handleGetToggleData(item)"
        >
          {{ item.name }}
        </span>
      </template>
      <template v-else>
        <div class="loading"></div>
      </template>
    </div>
  </div>
</template>

<script>
import { computed, reactive, ref } from "vue";
import { onClickOutside } from "@vueuse/core";
import axios from "axios";

export default {
  name: "XtxCity",
  props: ["location"],
  setup(props, { emit }) {
    let target = ref(null);
    // 下拉框是否显示
    let selectDownBox = ref(false);
    // 存放城市数据
    let cityData = ref([]);
    // 用于存储用户选择的城市数据
    const selectedCityData = reactive({
      provinceCode: "",
      cityCode: "",
      countyCode: "",
      provinceName: "",
      cityName: "",
      countyName: "",
      // 这个属性的作用是能够将省市区的数据回显
      location: "",
    });

    // 显示下拉框
    const show = () => {
      getCityData().then((res) => {
        // console.log(res);
        cityData.value = res;
      });

      selectDownBox.value = true;
    };

    // 隐藏下拉框
    const hide = () => {
      // console.log("hide");
      selectDownBox.value = false;
      // console.log(selectedCityData);
      // console.log(list);
      setTimeout(() => {
        for (let key in selectedCityData) {
          selectedCityData[key] = "";
        }
      });
    };

    // 点击显示/隐藏下拉框
    const handleShowSelectDown = () => {
      selectDownBox.value ? hide() : show();
    };

    // 点击获取该省市区数据
    const handleGetToggleData = (item) => {
      // console.log(item);
      // 如果在点击时进入判断后重置cityData数据的，代码过于冗杂，因此使用computed属性
      // 点击的是省数据
      if (item.level === 0) {
        // console.log("点击的是省数据");
        selectedCityData.provinceCode = item.code;
        selectedCityData.provinceName = item.name;
      }
      // 点击的是市数据
      if (item.level === 1) {
        // console.log("点击的是市数据");
        selectedCityData.cityCode = item.code;
        selectedCityData.cityName = item.name;
      }
      // 点击的是区数据
      if (item.level === 2) {
        // console.log("点击的是区数据");
        selectedCityData.countyCode = item.code;
        selectedCityData.countyName = item.name;

        // 回显数据
        selectedCityData.location = `${selectedCityData.provinceName} ${selectedCityData.countyName} ${selectedCityData.cityName}`;
        // console.log(selectedCityData.location);
      }
    };

    // 当点击在被监听的元素外时触发
    onClickOutside(target, () => {
      hide();
    });

    // 计算城市数据的变化替换
    let list = computed(() => {
      let result = cityData.value;
      // 如果点击了省级数据
      if (selectedCityData.provinceCode) {
        // console.log("点击了省级数据");
        result = result.find(
          (item) => item.code === selectedCityData.provinceCode
        ).areaList;
        // console.log(result);
      }

      // 如果点击了市级数据
      if (selectedCityData.cityCode) {
        // console.log("点击了市级数据");
        result = result.find(
          (item) => item.code === selectedCityData.cityCode
        ).areaList;
        // console.log(result);
      }

      // 如果点击了区级数据
      if (selectedCityData.countyCode) {
        // console.log("点击了区级数据");
        // 将获取到的省市区数据传输给父组件
        emit("handleChangeCityMes", selectedCityData.location);
        // result = cityData.value;
        // console.log(result);
        hide();
      }

      return result;
    });

    return {
      selectDownBox,
      handleShowSelectDown,
      target,
      list,
      handleGetToggleData,
    };
  },
};

// 每次点击都要发起请求，这不好，因此在 window 中存放城市数据
window.cityData = null;

// 获取城市数据
async function getCityData() {
  if (window.cityData) return window.cityData;

  let result = await axios.get(
    "https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/area.json"
  );

  return (window.cityData = result.data);
}
</script>

<style scoped lang="less">
.xtx-city {
  display: inline-block;
  position: relative;
  z-index: 400;

  .select {
    border: 1px solid #e4e4e4;
    height: 30px;
    padding: 0 5px;
    line-height: 28px;
    cursor: pointer;

    &.active {
      background: #fff;
    }

    .placeholder {
      color: #999;
    }

    .value {
      color: #666;
      font-size: 12px;
    }

    i {
      font-size: 12px;
      margin-left: 5px;
    }
  }

  .option {
    width: 542px;
    border: 1px solid #e4e4e4;
    position: absolute;
    left: 0;
    top: 29px;
    background: #fff;
    min-height: 30px;
    line-height: 30px;
    display: flex;
    flex-wrap: wrap;
    padding: 10px;

    > span {
      width: 130px;
      text-align: center;
      cursor: pointer;
      border-radius: 4px;
      padding: 0 3px;

      &:hover {
        background: #f5f5f5;
      }

      // 省略...
      .loading {
        height: 290px;
        width: 100%;
        background: url(../../assets/images/loading.gif) no-repeat center;
      }
    }
  }
}
</style>
